/**
 * Copyright (c) 2018-2022, NXOS Development Team
 * SPDX-License-Identifier: Apache-2.0
 *
 * Copyright(c) 2007-2022 Jianjun Jiang <8192542@qq.com>
 *          Official site: http://xboot.org
 *          Mobile phone: +86-18665388956
 *          QQ: 8192542
 *
 * Contains: nxos file system.
 *
 * Change Logs:
 * Date           Author            Notes
 * 2022-3-26      JasonHu           Port from xboot
 */

#include <vfsc.h>
#include <nxos/ipc.h>
#include <nxos/mman.h>

NX_Size VFS_Dispatch(NX_IpcMsg *ipcMsg)
{
	VFS_IpcReq *fr = NX_IpcGetMsgData(ipcMsg);
	// NX_Printf("vfs: type:%d\n", fr->type);
	switch (fr->type)
	{
	case VFS_REQ_OPEN:
	{
		struct VFS_OpenArgs *args = &fr->vfs_open_args;
		NX_Error err;
		int fd = VFS_FileOpen(args->path, args->flags, args->mode, &err);
		// if (fd != NX_EOK)
		// {
		// 	return -err;
		// }
		return fd;
	}
	case VFS_REQ_CLOSE:
	{
		struct VFS_CloseArgs *args = &fr->vfs_close_args;
		return VFS_FileClose(args->solt);
	}

	case VFS_REQ_READ:
	{
		struct VFS_ReadArgs *args = &fr->vfs_read_args;
		NX_Error err;
		NX_Solt shmMap = NX_SOLT_INVALID_VALUE;
		char *bufRead = args->buf;

		NX_Solt shm = NX_IpcGetMsgSolt(ipcMsg, 0);
		if (shm != NX_SOLT_INVALID_VALUE)
		{
			bufRead = NX_ShareMemMap(shm, &shmMap);
			if (!bufRead) {
				return 0;
			}
		}

		NX_U64 size = VFS_FileRead(args->solt, bufRead, args->len, &err);
		if (bufRead)
		{
			NX_ShareMemUnmap(shmMap);
		}

		// if (err != NX_EOK)
		// {
		// 	return -err;
		// }
		return size;
	}
	case VFS_REQ_WRITE:
	{
		struct VFS_WriteArgs *args = &fr->vfs_write_args;
		NX_Error err;
		NX_Solt shmMap = NX_SOLT_INVALID_VALUE;
		char *bufWrite = args->buf;

		NX_Solt shm = NX_IpcGetMsgSolt(ipcMsg, 0);
		if (shm != NX_SOLT_INVALID_VALUE)
		{
			bufWrite = NX_ShareMemMap(shm, &shmMap);
			if (!bufWrite) {
				return 0;
			}
		}

		NX_U64 size = VFS_FileWrite(args->solt, bufWrite, args->len, &err);
		if (bufWrite)
		{
			NX_ShareMemUnmap(shmMap);
		}
		// if (err != NX_EOK)
		// {
		// 	return -err;
		// }
		return size;
	}
	case VFS_REQ_IOCTL:
	{
		struct VFS_IoctlArgs *args = &fr->vfs_ioctl_args;
		return VFS_FileIoctl(args->solt, args->cmd, args->arg);
	}
	case VFS_REQ_LSEEK:
	{
		struct VFS_LseekArgs *args = &fr->vfs_lseek_args;
		NX_Error err;
		NX_Offset offset = VFS_FileSetPointer(args->solt, args->off, args->whence, &err);
		// if (err != NX_EOK)
		// {
		// 	return -err;
		// }
		return offset;
	}
	case VFS_REQ_FSYNC:
	{
		struct VFS_FsyncArgs *args = &fr->vfs_fsync_args;
		return VFS_FileSync(args->solt);
	}
	case VFS_REQ_FCHMOD:
	{
		struct VFS_FchmodArgs *args = &fr->vfs_fchmod_args;
		return VFS_FileSetMode(args->solt, args->mode);
	}
	case VFS_REQ_FSTAT:
	{
		struct VFS_FstatArgs *args = &fr->vfs_fstat_args;
		return VFS_FileGetStat(args->solt, &args->st);
	}
	case VFS_REQ_OPENDIR:
	{
		struct VFS_OpenDirArgs *args = &fr->vfs_opendir_args;
		NX_Error err;
		int fd = VFS_DirOpen(args->name, &err);
		// if (err != NX_EOK) {
		// 	return -err;
		// }
		return fd;
	}
	case VFS_REQ_CLOSEDIR:
	{
		struct VFS_CloseDirArgs *args = &fr->vfs_closedir_args;
		return VFS_DirClose(args->solt);
	}
	case VFS_REQ_READDIR:
	{
		struct VFS_ReadDirArgs *args = &fr->vfs_readdir_args;
		return VFS_DirRead(args->solt, &args->dir);
	}
	case VFS_REQ_REWINDDIR:
	{
		struct VFS_RewindDirArgs *args = &fr->vfs_rewinddir_args;
		return VFS_DirResetPointer(args->solt);
	}
	case VFS_REQ_MKDIR:
	{
		struct VFS_MkdirArgs *args = &fr->vfs_mkdir_args;
		return VFS_DirCreate(args->path, args->mode);
	}
	case VFS_REQ_RMDIR:
	{
		struct VFS_RmDirArgs *args = &fr->vfs_rmdir_args;
		return VFS_DirDelete(args->path);
	}
	case VFS_REQ_RENAME:
	{
		struct VFS_RenameArgs *args = &fr->vfs_rename_args;
		return VFS_FileRename(args->src, args->dst);
	}
	case VFS_REQ_UNLINK:
	{
		struct VFS_UnlinkArgs *args = &fr->vfs_unlink_args;
		return VFS_FileDelete(args->path);
	}
	case VFS_REQ_ACCESS:
	{
		struct VFS_AccessArgs *args = &fr->vfs_access_args;
		return VFS_FileAccess(args->path, args->mode);
	}
	case VFS_REQ_CHMOD:
	{
		struct VFS_ChmodArgs *args = &fr->vfs_chmod_args;
		return VFS_FileSetModeToPath(args->path, args->mode);
	}
	case VFS_REQ_STAT:
	{
		struct VFS_StatArgs *args = &fr->vfs_stat_args;
		return VFS_FileGetStatFromPath(args->path, &args->st);
	}

	default:
		break;
	}
}
